/*
 *  input.cc
 *  wonderland-project
 *
 *  Created by Ben Nolan on 13/10/08.
 *  Copyright 2008 Nolan Consulting Limited. All rights reserved.
 *
 */

#include <v8.h>
#include <Ogre.h>
#include <OIS/OIS.h>
#include "input.h"
#include "v8defines.h"
#include "input_listener.h"
#include "scripting_context.h"

namespace JSInput{
  OIS::Mouse  *mouse_;
  OIS::Keyboard *keyboard_;
  InputListener *listener_;
  
  v8::Handle<v8::ObjectTemplate> instance_template;
  v8::Handle<v8::FunctionTemplate> function_template;
  v8::Persistent<v8::Context> context_;

  V8CALLBACK(Input,isKeyDown){ 
    if(args.Length()!=1)
      return ThrowException(v8::String::New("Invalid argument"));

    return v8::Boolean::New(keyboard_->isKeyDown((OIS::KeyCode) args[0]->Int32Value()));
  }

  V8CALLBACK(Input,toggleGui){ 
	listener_->toggleGuiLayer();
	return v8::Undefined();
  }

  V8_GETTER(Input,enabled){
    return v8::Boolean::New(!listener_->isGuiVisible());
  }

  V8_GETTER(Input,leftMouseButton){
    return v8::Boolean::New(mouse_->getMouseState().buttonDown(OIS::MB_Left));
  }
  
  V8_GETTER(Input,rightMouseButton){
    return v8::Boolean::New(mouse_->getMouseState().buttonDown(OIS::MB_Right));
  }
  
  V8_GETTER(Input,mouseX){
    return v8::Number::New(mouse_->getMouseState().X.rel);
  }

  V8_GETTER(Input,mouseY){
    return v8::Number::New(mouse_->getMouseState().Y.rel);
  }

  V8_GETTER(Input,mouseZ){
    return v8::Number::New(mouse_->getMouseState().Z.rel);
  }

  /* Construct a new input object */
  V8CALLBACK(Input,create){
    if((!keyboard_) || (!mouse_))
      return ThrowException(v8::String::New("OIS is not instantiated"));
    
    v8::Persistent<v8::Object> self = v8::Persistent<v8::Object>::New(args.Holder());

    return self;
  }

  /* Called directly from c++ */
  v8::Handle<v8::Value> New(InputListener* listener){
    context_->Enter();

    listener_ = listener;
    keyboard_ = listener->getKeyboard();
    mouse_ = listener->getMouse();
    
    return v8::Persistent<v8::Object>::New(function_template->GetFunction()->NewInstance());
  }

  /* Create the function and instance templates  */

  void Initialize(Wonderland::ScriptingContext *sc){
    context_ = sc->getContext();

    // Function Template
    function_template = v8::FunctionTemplate::New(Input_create);
    function_template->SetClassName(v8::String::New("OISInput"));

    // Instance template
    instance_template = function_template->InstanceTemplate();
    instance_template->SetInternalFieldCount(2);

    instance_template->SetAccessor(v8::String::New("rightMouseButton"), Input_getrightMouseButton);
    instance_template->SetAccessor(v8::String::New("leftMouseButton"), Input_getleftMouseButton);
    instance_template->SetAccessor(v8::String::New("enabled"), Input_getenabled);
    instance_template->SetAccessor(v8::String::New("mouseX"), Input_getmouseX);
    instance_template->SetAccessor(v8::String::New("mouseY"), Input_getmouseY);
    instance_template->SetAccessor(v8::String::New("mouseZ"), Input_getmouseZ);
    instance_template->Set("isKeyDown", v8::FunctionTemplate::New(Input_isKeyDown));
    instance_template->Set("toggleGui", v8::FunctionTemplate::New(Input_toggleGui));

    // No constructor - since you can't create these via new OISInput
  }

}